package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.common.model.bean.JsonTmpMoMcInfo;
import cc.rengu.igas.momp.common.util.CommonMessageCheck;
import cc.rengu.igas.momp.common.util.JsonOperation;
import cc.rengu.igas.momp.common.util.McInfoDbOperation;
import cc.rengu.igas.momp.facade.bean.McMchntInfoBean;
import cc.rengu.igas.momp.facade.request.PublishMoneyOffMcRequest;
import cc.rengu.igas.momp.facade.response.PublishMoneyOffMcResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.bean.PageInfo;
import cc.rengu.oltp.utility.bean.PageResult;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 减免类营销活动发布
 * 只处理银行的营销活动发布
 *
 * @author Jinan Liu
 * @version 1.0.0
 * @date 2020/4/2 17:46
 */
public class PublishMoneyOffMcService extends RadpService {

    private String globalInstId;
    private String globalMcNo;
    private String globalTimeStamp;
    private String globalOprId;
    private String queryType;
    private String queryRole;
    private String oprType;
    private TMMcMoneyOffInfo tmMcMoneyOffInfo;
    private TMPlatBizTmp tmPlatBizTmp;
    private String mcStatus;
    private static final String TABLE_NAME = TableNameEnum.T_M_MC_MO_INFO.getTableNameCode();
    private String mcEndDtae;
    /**
     * 审批状态
     */
    private String auditStatus;
    /**
     * 拒绝原因
     */
    private String oprContent;
    /**
     * 状态
     */
    private String bizStatus;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            PublishMoneyOffMcRequest publishMoneyOffMcRequest = new PublishMoneyOffMcRequest();
            ConvertUtil.convertOutput(publishMoneyOffMcRequest);

            PublishMoneyOffMcResponse publishMoneyOffMcResponse = new PublishMoneyOffMcResponse();
            publishMoneyOffMcResponse.setHeader(publishMoneyOffMcRequest.getHeader());
            BizResponse<PublishMoneyOffMcResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(publishMoneyOffMcResponse);

            globalInstId = publishMoneyOffMcRequest.getHeader().getInstId();
            globalMcNo = publishMoneyOffMcRequest.getMcNo();
            globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
            globalOprId = publishMoneyOffMcRequest.getQueryId();

            rglog.info("机构<{}>的营销活动<{}>在<{}>由<{}>开始发布流程", globalInstId, globalMcNo, globalTimeStamp, globalOprId);

            queryType = publishMoneyOffMcRequest.getQueryType();
            queryRole = publishMoneyOffMcRequest.getQueryRole();
            oprType = publishMoneyOffMcRequest.getOprType();
            oprContent = publishMoneyOffMcRequest.getOprContent();

            /* 报文检查 */
            CommonMessageCheck.checkBizMessageHeader(queryType, globalOprId, queryRole, rglog);
            CommonMessageCheck.checkSingleValue(oprType, rglog);

            // 服务调用
            BizResponse<PublishMoneyOffMcResponse> bizResponseNew = publishMoneyOffMc(publishMoneyOffMcRequest, publishMoneyOffMcResponse, xmlTreeUtil);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }


    /**
     * 发布减免类营销活动
     * 仅处理银行人员的活动发布
     * 商户自己的发布流程在另外的接口实现
     *
     * @param publishMoneyOffMcRequest  减免类活动发布接口请求对象
     * @param publishMoneyOffMcResponse 减免类活动发布接口应答对象
     * @param xmlTreeUtil               内部XML树
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.PublishMoneyOffMcResponse> 减免类活动发布接口应答对象
     * @throws BizException 异常信息
     * @author Jinan Liu
     * @date 2020/5/23 16:59
     */
    private BizResponse<PublishMoneyOffMcResponse> publishMoneyOffMc(PublishMoneyOffMcRequest publishMoneyOffMcRequest, PublishMoneyOffMcResponse publishMoneyOffMcResponse, XmlTreeUtil xmlTreeUtil)
            throws Exception {

        BizResponse<PublishMoneyOffMcResponse> bizResponse = new BizResponse<>();

        /* 判断用户的角色和权限 */
        if (QueryRoleEnum.BANK_PUBLISH_QYERY_ROLE.getQueryRoleCode().equals(queryRole)) {
            /* 银行录入岗操作 */
            if (QueryTypeEnum.BANK_QUERY_TYPE.getQueryTypeCode().equals(queryType)) {

                /* 取营销活动正式表和临时表的各种状态 */
                checkMcStatus(publishMoneyOffMcRequest.getOprType());

                /* 判断操作类型 */
                if (OprTypeEnum.PUBLISH_PASSED.getOprTypeCode().equals(oprType)) {
                    /* 发布通过 */
                    publishMc(xmlTreeUtil, publishMoneyOffMcRequest);
                } else if (OprTypeEnum.PUBLISH_REFUSED.getOprTypeCode().equals(oprType)) {
                    /* 发布拒绝 */
                    refusePublishMc(xmlTreeUtil, publishMoneyOffMcRequest);
                } else if (OprTypeEnum.ENABLE.getOprTypeCode().equals(oprType)) {
                    /* 启用活动 */
                    enableMc(xmlTreeUtil);
                } else if (OprTypeEnum.PAUSE.getOprTypeCode().equals(oprType)) {
                    /* 暂停活动 */
                    pauseMc(xmlTreeUtil);
                } else if (OprTypeEnum.FORCE_DISABLE.getOprTypeCode().equals(oprType)) {
                    /* 强制终止活动 */
                    forceStopMc(xmlTreeUtil);
                } else {
                    /* 不支持的操作类型 */
                    rglog.error("<{}>, OPR_TYPE=<{}>", RespCodeEnum.NOT_SUPPORTED_OPR_TYPE_ERROR.getRespDesc(), oprType);
                    throw new BizException(RespCodeEnum.NOT_SUPPORTED_OPR_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SUPPORTED_OPR_TYPE_ERROR.getRespDesc());
                }

            } else {
                /* 非银行人员无权限操作数据 */
                rglog.error("当前<{}>角色的查询用户<{}>无权限操作数据!", queryRole, queryType);
                throw new BizException(RespCodeEnum.NO_AUTHORIZATION_TO_OPER_ERROR.getRespCode(), RespCodeEnum.NO_AUTHORIZATION_TO_OPER_ERROR.getRespDesc());
            }

        } else {
            /* 非银行发布岗无权限操作数据 */
            rglog.error("当前<{}>角色的查询用户<{}>无权限操作数据!", queryRole, queryType);
            throw new BizException(RespCodeEnum.NO_AUTHORIZATION_TO_OPER_ERROR.getRespCode(), RespCodeEnum.NO_AUTHORIZATION_TO_OPER_ERROR.getRespDesc());
        }

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        publishMoneyOffMcResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        publishMoneyOffMcResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(publishMoneyOffMcResponse);

        return bizResponse;
    }

    /**
     * 判断营销活动状态是否可以发布通过或者发布拒绝
     * 未抛异常说明营销活动状态正常
     * 全局变量mcStatus作为判断当前营销活动是否发布的标志
     *
     * @param oprType 操作类型
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/25 22:10
     */
    private void checkMcStatus(String oprType) throws Exception {

        /* 查询正式表数据 */
        TMMcMoneyOffInfo tmMcMoneyOffInfo = (TMMcMoneyOffInfo) McInfoDbOperation.getMcInfo(rglog, globalInstId, globalMcNo, TABLE_NAME);
        if (null == tmMcMoneyOffInfo) {
            rglog.error("未获取到机构<{}>的营销活动编号<{}>的营销活动基本信息", globalInstId, globalMcNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        this.tmMcMoneyOffInfo = tmMcMoneyOffInfo;
        mcEndDtae = tmMcMoneyOffInfo.getMcEndDate();

        /* 查询临时表数据 */
        TMPlatBizTmp tmPlatBizTmp = McInfoDbOperation.getTmpMcInfo(rglog, globalInstId, globalMcNo, TABLE_NAME);
        if (null == tmPlatBizTmp) {
            rglog.error("未获取到机构<{}>的营销活动编号<{}>的营销活动基本信息", globalInstId, globalMcNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }


        if (OprTypeEnum.PUBLISH_PASSED.getOprTypeCode().equals(oprType) ||
                OprTypeEnum.PUBLISH_REFUSED.getOprTypeCode().equals(oprType)) {
            /* 发布营销活动检查项，和拒绝发布流程相同，共用一套判断流程 */
            /* 拒绝发布营销活动检查项，和发布通过流程相同，共用一套判断流程 */
            /* 临时表中营销活动状态不是未发布的不可发布通过 */
            if (!McStatusEnum.NOT_PUBLISHED.getMcStatusCode().equals(tmPlatBizTmp.getMcStatus()) && !McStatusEnum.PROGRESSING.getMcStatusCode().equals(tmPlatBizTmp.getMcStatus())) {
                rglog.error("机构<{}>的营销活动编号<{}>临时表中的营销活动状态<{}>异常，不可发布通过或发布拒绝", globalInstId, globalMcNo, tmPlatBizTmp.getMcStatus());
                throw new BizException(RespCodeEnum.WRONG_TMP_MC_STATUS_TO_PASS_PUBLISH_ERROR.getRespCode(), RespCodeEnum.WRONG_TMP_MC_STATUS_TO_PASS_PUBLISH_ERROR.getRespDesc());
            }

            /* 临时表中营销活动审批状态不是发布审批中的不可发布通过 */
            if (!AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode().equals(tmPlatBizTmp.getAuditStatus())) {
                rglog.error("机构<{}>的营销活动编号<{}>临时表中的营销活动审批状态<{}>异常，不可发布通过或发布拒绝", globalInstId, globalMcNo, tmPlatBizTmp.getAuditStatus());
                throw new BizException(RespCodeEnum.WRONG_TMP_AUDIT_STATUS_TO_REFUSE_PUBLISH_ERROR.getRespCode(), RespCodeEnum.WRONG_TMP_AUDIT_STATUS_TO_REFUSE_PUBLISH_ERROR.getRespDesc());
            }

            /* 判断营销活动是否在进行中 */
            if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(this.tmMcMoneyOffInfo.getMcStatus())) {
                /* 营销活动在进行中 */
                this.mcStatus = McStatusEnum.PROGRESSING.getMcStatusCode();
            } else {
                /* 营销活动不是进行中的状态 */
                if (!McStatusEnum.NOT_PUBLISHED.getMcStatusCode().equals(this.tmMcMoneyOffInfo.getMcStatus())) {
                    rglog.error("机构<{}>的营销活动编号<{}>的营销活动状态<{}>异常，不可发布通过或发布拒绝", globalInstId, globalMcNo, this.tmMcMoneyOffInfo.getMcStatus());
                    throw new BizException(RespCodeEnum.WRONG_MC_STATUS_TO_PASS_PUBLISH_ERROR.getRespCode(), RespCodeEnum.WRONG_MC_STATUS_TO_PASS_PUBLISH_ERROR.getRespDesc());
                }

                if (!AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode().equals(this.tmMcMoneyOffInfo.getAuditStatus())) {
                    rglog.error("机构<{}>的营销活动编号<{}>的营销活动审批状态<{}>异常，不可发布通过或发布拒绝", globalInstId, globalMcNo, this.tmMcMoneyOffInfo.getAuditStatus());
                    throw new BizException(RespCodeEnum.WRONG_AUDIT_STATUS_TO_REFUSE_PUBLISH_ERROR.getRespCode(), RespCodeEnum.WRONG_AUDIT_STATUS_TO_REFUSE_PUBLISH_ERROR.getRespDesc());
                }

                this.mcStatus = McStatusEnum.NOT_PUBLISHED.getMcStatusCode();
            }
        } else if (oprType.equals(OprTypeEnum.FORCE_DISABLE.getOprTypeCode())) {//活动强制终止
            if ((!this.tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.PROGRESSING.getMcStatusCode()) && !this.tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.PAUSED.getMcStatusCode()))) {
                rglog.error("机构<{}>的营销活动编号<{}>的营销活动状态<{}>不是进行中或已暂停，不可强制终止", globalInstId, globalMcNo, this.tmMcMoneyOffInfo.getMcStatus());
                throw new BizException(RespCodeEnum.WRONG_MC_STATUS_TO_FORCE_DISABLE_ERROR.getRespCode(), RespCodeEnum.WRONG_MC_STATUS_TO_FORCE_DISABLE_ERROR.getRespDesc());
            }
        } else if (oprType.equals(OprTypeEnum.PAUSE.getOprTypeCode())) {//活动暂停
            if (!this.tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.PROGRESSING.getMcStatusCode())) {
                rglog.error("机构<{}>的营销活动编号<{}>的营销活动状态<{}>不是进行中，不可暂停", globalInstId, globalMcNo, this.tmMcMoneyOffInfo.getMcStatus());
                throw new BizException(RespCodeEnum.WRONG_MC_STATUS_TO_PAUSE_ERROR.getRespCode(), RespCodeEnum.WRONG_MC_STATUS_TO_PAUSE_ERROR.getRespDesc());
            }
        } else if (oprType.equals(OprTypeEnum.ENABLE.getOprTypeCode())) {//活动启用
            if (!this.tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.PAUSED.getMcStatusCode())) {
                rglog.error("机构<{}>的营销活动编号<{}>的营销活动状态<{}>不是已暂停，不可启用活动", globalInstId, globalMcNo, this.tmMcMoneyOffInfo.getMcStatus());
                throw new BizException(RespCodeEnum.WRONG_MC_STATUS_TO_ENABLE_ERROR.getRespCode(), RespCodeEnum.WRONG_MC_STATUS_TO_ENABLE_ERROR.getRespDesc());
            }
        } else {
            /* 不支持的操作类型 */
            rglog.error("<{}>, OPR_TYPE=<{}>", RespCodeEnum.NOT_SUPPORTED_OPR_TYPE_ERROR.getRespDesc(), oprType);
            throw new BizException(RespCodeEnum.NOT_SUPPORTED_OPR_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SUPPORTED_OPR_TYPE_ERROR.getRespDesc());
        }
    }

    /**
     * 营销活动发布通过流程
     *
     * @param xmlTreeUtil              内部XML树
     * @param publishMoneyOffMcRequest 减免类活动发布接口请求对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/25 22:50
     */
    private void publishMc(XmlTreeUtil xmlTreeUtil, PublishMoneyOffMcRequest publishMoneyOffMcRequest) throws Exception {
        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();
        /* 根据营销活动状态走入对应的业务流程 */
        int returnCode;
        if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(this.mcStatus)) {

            /* 取新增商户数据 */
            TMPlatBizTmp tmPlatBizTmp = new TMPlatBizTmp();
            tmPlatBizTmp.setInstId(globalInstId);
            tmPlatBizTmp.setMcNo(globalMcNo);
            tmPlatBizTmp.setOprTableEname(TableNameEnum.T_M_MC_MCHNT_INFO.getTableNameCode());
            tmPlatBizTmp.setBizStatus(BizStatusEnum.NORMAL_STATUS.getBizStatusCode());
            tmPlatBizTmp.setMcStatus(McStatusEnum.NOT_PUBLISHED.getMcStatusCode());
            tmPlatBizTmp.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode());
            List<TMPlatBizTmp> tmPlatBizTmpList = selectNewAddedMchntInfoForPublishing(tmPlatBizTmp);
            PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
            McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
            if (null == tmPlatBizTmpList || tmPlatBizTmpList.isEmpty()) {
                TMMcMoneyOffInfo tmMcMoneyOffInfo1 = new TMMcMoneyOffInfo();
                tmMcMoneyOffInfo1.setInstId(globalInstId);
                tmMcMoneyOffInfo1.setMcNo(globalMcNo);
                tmMcMoneyOffInfo1.setMcStatus(McStatusEnum.PROGRESSING.getMcStatusCode());
                tmMcMoneyOffInfo1.setRemark1(AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode());
                tmMcMoneyOffInfo1.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_PASSED.getAuditStatusCode());
                /* 更新营销活动预算数据 */
                returnCode = mcDetailInfoMapper.updataMcStatusForPublish(tmMcMoneyOffInfo1);
                if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新机构<{}>商户手续费优惠类营销活动<{}>营销活动状态失败!", globalInstId, globalMcNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
            } else {

                /* 解析商户数据 */
                List<TMMcMchntInfo> tmMcMchntInfoList = JsonOperation.parseMcMchntInfoTmpBizData1(rglog, tmPlatBizTmpList);
                if (tmMcMchntInfoList.isEmpty()) {
                    rglog.error("解析机构<{}>营销活动<{}>待发布商户规则数据失败!", globalInstId, globalMcNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }

                /* 取原纪录创建人和记录创建时间 */
                for (TMMcMchntInfo tmMcMchntInfo : tmMcMchntInfoList) {
                    tmMcMchntInfo.setOprId(tmPlatBizTmpList.get(CommonConstant.ZERO).getOprId());
                    tmMcMchntInfo.setCreateTime(tmPlatBizTmpList.get(CommonConstant.ZERO).getCreateTime());
                    tmMcMchntInfo.setExitFlag(CommonConstant.MC_NOT_EXIT_FLAG);
                    tmMcMchntInfo.setNewMchntFlag(CommonConstant.MCHNT_OLD_FLAG);
                }

                /* 修改正式表商户数据 */
                returnCode = updateMcMchntInfoListByBank(tmMcMchntInfoList);
                if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新机构<{}>减免类营销活动<{}>营销活动基本信息预算数据失败!", globalInstId, globalMcNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
                TMPlatBizTmp tmPlatBizTmp1 = platBizTmpMapper.selectTmpMcInfo(publishMoneyOffMcRequest.getHeader().getInstId(), publishMoneyOffMcRequest.getMcNo(), TableNameEnum.T_M_MC_MO_INFO.getTableNameCode());
                /* 解析减免类营销活动信息临时表预算数据并计算银行出资比例 */
                JsonTmpMoMcInfo jsonTmpMoMcInfo = (JsonTmpMoMcInfo) JsonOperation.parseMcInfoTmpBizData1(rglog, tmPlatBizTmp1, TABLE_NAME);
                if (null == jsonTmpMoMcInfo) {
                    rglog.error("解析机构<{}>减免类营销活动<{}>营销活动基本信息临时表数据失败!", globalInstId, globalMcNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }

                BigDecimal budget = new BigDecimal(jsonTmpMoMcInfo.getBudget()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal bankBudget = new BigDecimal(jsonTmpMoMcInfo.getBankBudget()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal bankBudgetRatio = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                if (CommonConstant.IS_EQUAL_TO == BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).compareTo(budget)) {
                    bankBudgetRatio = bankBudget.divide(budget, CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                }

                TMMcMoneyOffInfo tmMcMoneyOffInfo1 = new TMMcMoneyOffInfo();
                tmMcMoneyOffInfo1.setInstId(globalInstId);
                tmMcMoneyOffInfo1.setMcNo(globalMcNo);
                tmMcMoneyOffInfo1.setBudget(jsonTmpMoMcInfo.getBudget());
                tmMcMoneyOffInfo1.setBankBudget(jsonTmpMoMcInfo.getBankBudget());
                tmMcMoneyOffInfo1.setExpectMchntQty(jsonTmpMoMcInfo.getExpectMchntQty());
                tmMcMoneyOffInfo1.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_PASSED.getAuditStatusCode());
                tmMcMoneyOffInfo1.setBankBudgetRatio(bankBudgetRatio.toString());

                /* 更新营销活动预算数据 */
                returnCode = updateMcBudgetForPublishing(tmMcMoneyOffInfo1);
                if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新机构<{}>减免类营销活动<{}>营销活动基本信息预算数据失败!", globalInstId, globalMcNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
                int returnCodes = platBizTmpMapper.updataTMPlatBizByList(tmPlatBizTmpList, "publish");
                if (Database.DBS_SUCCESS != returnCodes) {
                    rglog.error("更新机构<{}>减免类营销活动<{}>营销活动基本信息失败!", globalInstId, globalMcNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
            }
        } else {
            //判断批量任务是否处理成功，如果否直接拒掉
            /* 营销活动信息正式表查询 */
            McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
            TMMcMoneyOffInfo tmMcMoneyOffInfo = (TMMcMoneyOffInfo) mcDetailInfoMapper.selectMcDetailInfo(globalInstId, globalMcNo, TableNameEnum.T_M_MC_MO_INFO.getTableNameCode());
            if (null == tmMcMoneyOffInfo) {
                /* 异常结束数据库事务 */
                rglog.error("查询营销活动信息失败, INST_ID=<{}>, MC_NO=<{}>", globalInstId, globalMcNo);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
            //查询营销活动商户信息表  改为分页查询
            McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
            TMMcMchntInfo tmMcMchntInfo = mcMchntInfoMapper.selectMcMchntInfoListCount(tmMcMoneyOffInfo.getInstId(), tmMcMoneyOffInfo.getMcNo());
            int mcMchntListSize = Integer.valueOf(tmMcMchntInfo.getRemark5());

            if (tmMcMoneyOffInfo.getPublishBatchStatus().equals(CommonConstant.ZERO_COMMON_CONSTANT) && mcMchntListSize == 0) {
                rglog.error("批量任务未处理成功, INST_ID=<{}>, MC_NO=<{}>", globalInstId, globalMcNo);
                throw new BizException(RespCodeEnum.FAILED_TO_RUN_TIME_TASK.getRespCode(), RespCodeEnum.FAILED_TO_RUN_TIME_TASK.getRespDesc());
            }
            if (tmMcMoneyOffInfo.getPublishBatchStatus().equals(CommonConstant.TWO_COMMON_CONSTANT) && mcMchntListSize == 0) {
                rglog.error("批量任务处理失败, INST_ID=<{}>, MC_NO=<{}>", globalInstId, globalMcNo);
                throw new BizException(RespCodeEnum.TIME_TASK_RUN_FAILED.getRespCode(), RespCodeEnum.TIME_TASK_RUN_FAILED.getRespDesc());
            }
            /* 若营销活动状态为未发布，需要更新减免类营销活动信息表的营销活动状态和审批状态 */

            /* 更新正式表营销活动状态和审批状态 */
            TMMcMoneyOffInfo tmMcMoneyOffInfo1 = new TMMcMoneyOffInfo();
            tmMcMoneyOffInfo1.setInstId(globalInstId);
            tmMcMoneyOffInfo1.setMcNo(globalMcNo);
            tmMcMoneyOffInfo1.setMcStatus(McStatusEnum.PROGRESSING.getMcStatusCode());
            tmMcMoneyOffInfo1.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_PASSED.getAuditStatusCode());
            tmMcMoneyOffInfo1.setLastOprId(globalOprId);
            tmMcMoneyOffInfo1.setUpdateTime(globalTimeStamp);
            returnCode = updateMcStatusForPublishing(tmMcMoneyOffInfo1);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("发布成功更新减免类营销活动信息表失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        }

        /* 更新业务数据临时表状态 */
        TMPlatBizTmp tmPlatBizTmp1 = new TMPlatBizTmp();
        tmPlatBizTmp1.setInstId(globalInstId);
        tmPlatBizTmp1.setMcNo(globalMcNo);
        tmPlatBizTmp1.setBizOpr(BizOprEnum.PUBLISH.getBizOprCode());
        tmPlatBizTmp1.setMcStatus(McStatusEnum.PROGRESSING.getMcStatusCode());
        tmPlatBizTmp1.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_PASSED.getAuditStatusCode());
        returnCode = updateSingleMcInfoForPublishing(tmPlatBizTmp1);
        if (Database.DBS_SUCCESS != returnCode) {
            rglog.error("发布成功更新业务数据临时表失败！RETURN_CODE=<{}>", returnCode);
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        dbsUtil.dbsEndTransaction(true);
    }

    /**
     * 营销活动发布拒绝流程
     *
     * @param xmlTreeUtil              内部XML树
     * @param publishMoneyOffMcRequest 减免类活动发布接口请求对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 00:50
     */
    private void refusePublishMc(XmlTreeUtil xmlTreeUtil, PublishMoneyOffMcRequest publishMoneyOffMcRequest) throws Exception {

        int returnCode;

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();
        if (!McStatusEnum.PROGRESSING.getMcStatusCode().equals(this.mcStatus)) {
            /* 更新临时表状态 */
            TMPlatBizTmp tmPlatBizTmp = new TMPlatBizTmp();
            tmPlatBizTmp.setInstId(globalInstId);
            tmPlatBizTmp.setMcNo(globalMcNo);
            tmPlatBizTmp.setBizStatus(BizStatusEnum.NORMAL_STATUS.getBizStatusCode());
            tmPlatBizTmp.setMcStatus(McStatusEnum.NOT_PUBLISHED.getMcStatusCode());
            tmPlatBizTmp.setBizOpr(BizOprEnum.RETURN.getBizOprCode());
            tmPlatBizTmp.setAuditRefuseReason(publishMoneyOffMcRequest.getOprContent());
            tmPlatBizTmp.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_REJECT.getAuditStatusCode());
            tmPlatBizTmp.setLastOprId(globalOprId);
            tmPlatBizTmp.setLastUpdateTime(globalTimeStamp);
            returnCode = updateMcAuditStatusForPublishingRefusal(tmPlatBizTmp);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("发布失败更新业务数据临时表失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        }
        /* 只有未发布状态的营销活动更新正式表数据 */
        if (McStatusEnum.NOT_PUBLISHED.getMcStatusCode().equals(this.mcStatus)) {
            //判断批量任务是否处理成功，如果否直接拒掉
            McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
            TMMcMchntInfo tmMcMchntInfo = mcMchntInfoMapper.selectMcMchntInfoListCount(tmMcMoneyOffInfo.getInstId(), tmMcMoneyOffInfo.getMcNo());
            int mcMchntListSize = Integer.valueOf(tmMcMchntInfo.getRemark5());
            if (this.tmMcMoneyOffInfo.getPublishBatchStatus().equals(CommonConstant.ZERO_COMMON_CONSTANT) && mcMchntListSize == 0) {
                rglog.error("批量任务未处理成功, INST_ID=<{}>, MC_NO=<{}>", globalInstId, globalMcNo);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.FAILED_TO_RUN_TIME_TASK.getRespCode(), RespCodeEnum.FAILED_TO_RUN_TIME_TASK.getRespDesc());
            }
            if (this.tmMcMoneyOffInfo.getPublishBatchStatus().equals(CommonConstant.TWO_COMMON_CONSTANT) && mcMchntListSize == 0) {
                rglog.error("批量任务处理失败, INST_ID=<{}>, MC_NO=<{}>", globalInstId, globalMcNo);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.TIME_TASK_RUN_FAILED.getRespCode(), RespCodeEnum.TIME_TASK_RUN_FAILED.getRespDesc());
            }
            //查询打款记录表是否有记录
            TMMcFundInfoMapper tmMcFundInfoMapper = new TMMcFundInfoMapperImpl();
            TMMcFundInfo tmMcFundInfo = new TMMcFundInfo();
            tmMcFundInfo.setInstId(globalInstId);
            tmMcFundInfo.setMcNo(globalMcNo);
            int code = tmMcFundInfoMapper.checkMaxmiumRecordIndexInfoByInstIdMcNo(tmMcFundInfo);
            //code大于0 存在打款成功的记录 不允许
            if (code > CommonConstant.ZERO) {
                dbsUtil.dbsEndTransaction(false);
                rglog.info("存在打款成功的记录，不允许发布拒绝退回");
                throw new BizException(RespCodeEnum.MC_FUND_SUCCESS_NOT_ALLOWED_TO_REFUSE_PUBLISH.getRespCode(), RespCodeEnum.MC_FUND_SUCCESS_NOT_ALLOWED_TO_REFUSE_PUBLISH.getRespDesc());
            }
            TMMcMoneyOffInfo tmMcMoneyOffInfo = new TMMcMoneyOffInfo();
            tmMcMoneyOffInfo.setInstId(globalInstId);
            tmMcMoneyOffInfo.setMcNo(globalMcNo);
            tmMcMoneyOffInfo.setRemark1(AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode());
            tmMcMoneyOffInfo.setMcStatus(McStatusEnum.NOT_PUBLISHED.getMcStatusCode());
            tmMcMoneyOffInfo.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_REJECT.getAuditStatusCode());
            tmMcMoneyOffInfo.setPublishRefuseReason(publishMoneyOffMcRequest.getOprContent());
            tmMcMoneyOffInfo.setLastOprId(globalOprId);
            tmMcMoneyOffInfo.setUpdateTime(globalTimeStamp);

            returnCode = updateMcAuditStatusForPublishRefusal(tmMcMoneyOffInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("发布失败更新减免类营销活动信息表失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        } else if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(this.mcStatus)) {
            PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
            //更新临时表活动状态为发布拒绝
            TMPlatBizTmp tmPlatBizTmp = new TMPlatBizTmp();
            tmPlatBizTmp.setBizStatus(BizStatusEnum.NORMAL_STATUS.getBizStatusCode());
            tmPlatBizTmp.setMcStatus(McStatusEnum.NOT_PUBLISHED.getMcStatusCode());
            tmPlatBizTmp.setOprTableEname(TableNameEnum.T_M_MC_MO_INFO.getTableNameCode());
            tmPlatBizTmp.setOprTableCname(TableNameEnum.T_M_MC_MO_INFO.getTableNameDesc());
            tmPlatBizTmp.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_REJECT.getAuditStatusCode());
            returnCode = platBizTmpMapper.updataTMPlatBizByinstIdMcNoTableNameAuditStatus(globalInstId, globalMcNo, tmPlatBizTmp, AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode(), "", "");
            if (cc.rengu.utility.dbs.Database.DBS_SUCCESS != returnCode) {
                /* 营销活动临时数据审批状态异常，不可审批通过 */
                dbsUtil.dbsEndTransaction(false);
                rglog.error("{}, RETURN_CODE=<{}>, MC_NO=<{}>", RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc(), returnCode, globalMcNo);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
            tmPlatBizTmp.setOprTableCname(TableNameEnum.T_M_MC_MCHNT_INFO.getTableNameDesc());
            tmPlatBizTmp.setOprTableEname(TableNameEnum.T_M_MC_MCHNT_INFO.getTableNameCode());
            returnCode = platBizTmpMapper.updataTMPlatBizByinstIdMcNoTableNameAuditStatus(globalInstId, globalMcNo, tmPlatBizTmp, AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode(), "", "");
            if (cc.rengu.utility.dbs.Database.DBS_SUCCESS != returnCode && cc.rengu.utility.dbs.Database.DBS_NOT_FOUND != returnCode) {
                /* 营销活动临时数据审批状态异常，不可审批通过 */
                dbsUtil.dbsEndTransaction(false);
                rglog.error("{}, RETURN_CODE=<{}>, MC_NO=<{}>", RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc(), returnCode, globalMcNo);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
            //正式表更新减免类活动为发布拒绝状态
            TMMcMoneyOffInfo tmMcMoneyOffInfo = new TMMcMoneyOffInfo();
            tmMcMoneyOffInfo.setInstId(globalInstId);
            tmMcMoneyOffInfo.setMcNo(globalMcNo);
            tmMcMoneyOffInfo.setRemark1(AuditStatusEnum.PUBLISH_AUDIT_PROCESSING.getAuditStatusCode());
            tmMcMoneyOffInfo.setMcStatus(McStatusEnum.PROGRESSING.getMcStatusCode());
            tmMcMoneyOffInfo.setAuditStatus(AuditStatusEnum.PUBLISH_AUDIT_REJECT.getAuditStatusCode());
            tmMcMoneyOffInfo.setPublishRefuseReason(publishMoneyOffMcRequest.getOprContent());
            tmMcMoneyOffInfo.setLastOprId(globalOprId);
            tmMcMoneyOffInfo.setUpdateTime(globalTimeStamp);

            returnCode = updateMcAuditStatusForPublishRefusal(tmMcMoneyOffInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("发布失败更新减免类营销活动信息表失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            //查询营销商户表数据
            List<Object> tmMcMchntInfoObjList = getAllMcMchntListInfoByinstIdMcMoFlag(CommonConstant.MC_EXIT_FLAG, CommonConstant.MCHNT_NEW_FLAG);
            List<TMMcMchntInfo> tmMcMchntInfoList = tmMcMchntInfoObjList.stream().map(item -> (TMMcMchntInfo) (item)).collect(Collectors.toList());

            McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
            if (null != tmMcMchntInfoList && tmMcMchntInfoList.size() > 0) {
                for (TMMcMchntInfo tmMcMchntInfo : tmMcMchntInfoList) {
                    tmMcMchntInfo.setNewMchntFlag(CommonConstant.MCHNT_REFUSE_FLAG);
                }
                returnCode = mcMchntInfoMapper.updateMcMchntInfoListByBank(tmMcMchntInfoList);
                if (cc.rengu.utility.dbs.Database.DBS_SUCCESS != returnCode) {
                    /* 营销活动审批状态异常，不可审批通过 */
                    dbsUtil.dbsEndTransaction(false);
                    rglog.error("{}, RETURN_CODE=<{}>, MC_NO=<{},营销活动商户正式表数据更新失败>", RespCodeEnum.WRONG_UPDATEMCMCHNT_ERROR.getRespDesc(), returnCode, globalMcNo);
                    throw new BizException(RespCodeEnum.WRONG_UPDATEMCMCHNT_ERROR.getRespCode(), RespCodeEnum.WRONG_UPDATEMCMCHNT_ERROR.getRespDesc());
                }
            }
        }

        dbsUtil.dbsEndTransaction(true);
    }

    /**
     * 启用已暂停营销活动
     *
     * @param xmlTreeUtil 内部XML树
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:28
     */
    private void enableMc(XmlTreeUtil xmlTreeUtil) throws Exception {

        int returnCode;

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        /* 检查减免类营销活动信息表的正式表中的营销活动状态 */
        if (McStatusEnum.PAUSED.getMcStatusCode().equals(tmMcMoneyOffInfo.getMcStatus())) {

            /* 更新正式表数据状态 */
            TMMcMoneyOffInfo tmMcMoneyOffInfo = new TMMcMoneyOffInfo();
            tmMcMoneyOffInfo.setInstId(globalInstId);
            tmMcMoneyOffInfo.setMcNo(globalMcNo);
            tmMcMoneyOffInfo.setMcStatus(McStatusEnum.PROGRESSING.getMcStatusCode());
            tmMcMoneyOffInfo.setLastOprId(globalOprId);
            tmMcMoneyOffInfo.setUpdateTime(globalTimeStamp);
            tmMcMoneyOffInfo.setMcEndDate(mcEndDtae);

            returnCode = updatePausedMcMcStatusForEnabling(tmMcMoneyOffInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("启用已暂停减免类营销活动信息正式表失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            //查询临时表状态
            checkTmPStatus(globalInstId, globalMcNo);
            /* 更新临时表数据状态 */
            TMPlatBizTmp tmPlatBizTmp = new TMPlatBizTmp();
            tmPlatBizTmp.setInstId(globalInstId);
            tmPlatBizTmp.setMcNo(globalMcNo);
            tmPlatBizTmp.setBizOpr(BizOprEnum.ENABLE.getBizOprCode());
            tmPlatBizTmp.setBizStatus(bizStatus);
            tmPlatBizTmp.setMcStatus(McStatusEnum.PROGRESSING.getMcStatusCode());
            tmPlatBizTmp.setAuditStatus(auditStatus);
            tmPlatBizTmp.setLastOprId(globalOprId);
            tmPlatBizTmp.setLastUpdateTime(globalTimeStamp);

            returnCode = updatePausedMcForEnabling(tmPlatBizTmp);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("启用已暂停减免类营销活动信息临时表失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

        } else {
            rglog.error("营销活动状态异常，不可启用营销活动！MC_STATUS=<{}>", tmMcMoneyOffInfo.getMcStatus());
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        dbsUtil.dbsEndTransaction(true);
    }

    /**
     * 暂停进行中营销活动
     *
     * @param xmlTreeUtil 内部XML树
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:46
     */
    private void pauseMc(XmlTreeUtil xmlTreeUtil) throws Exception {

        int returnCode;

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        /* 检查减免类营销活动信息表的正式表中的营销活动状态 */
        if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(tmMcMoneyOffInfo.getMcStatus())) {

            /* 更新正式表数据状态 */
            TMMcMoneyOffInfo tmMcMoneyOffInfo = new TMMcMoneyOffInfo();
            tmMcMoneyOffInfo.setInstId(globalInstId);
            tmMcMoneyOffInfo.setMcNo(globalMcNo);
            tmMcMoneyOffInfo.setMcStatus(McStatusEnum.PAUSED.getMcStatusCode());
            tmMcMoneyOffInfo.setLastOprId(globalOprId);
            tmMcMoneyOffInfo.setUpdateTime(globalTimeStamp);
            tmMcMoneyOffInfo.setMcEndDate(mcEndDtae);

            returnCode = updatePausedMcMcStatusForEnabling(tmMcMoneyOffInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("暂停进行中减免类营销活动信息更新正式表数据失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            //查询临时表状态
            checkTmPStatus(globalInstId, globalMcNo);
            /* 更新临时表数据状态 */
            TMPlatBizTmp tmPlatBizTmp = new TMPlatBizTmp();
            tmPlatBizTmp.setInstId(globalInstId);
            tmPlatBizTmp.setMcNo(globalMcNo);
            tmPlatBizTmp.setBizOpr(BizOprEnum.SUSPEND.getBizOprCode());
            tmPlatBizTmp.setBizStatus(bizStatus);
            tmPlatBizTmp.setMcStatus(McStatusEnum.PAUSED.getMcStatusCode());
            tmPlatBizTmp.setAuditStatus(auditStatus);
            tmPlatBizTmp.setLastOprId(globalOprId);
            tmPlatBizTmp.setLastUpdateTime(globalTimeStamp);

            returnCode = updatePausedMcForEnabling(tmPlatBizTmp);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("暂停进行中减免类营销活动信息更新临时表数据失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

        } else {
            rglog.error("营销活动状态异常，不可暂停进行中的减免类营销活动！MC_STATUS=<{}>", tmMcMoneyOffInfo.getMcStatus());
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        dbsUtil.dbsEndTransaction(true);
    }

    /**
     * 强制结束进行中营销活动
     *
     * @param xmlTreeUtil 内部XML树
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:52
     */
    private void forceStopMc(XmlTreeUtil xmlTreeUtil) throws Exception {

        int returnCode;

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        /* 检查减免类营销活动信息表的正式表中的营销活动状态 */
        if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(tmMcMoneyOffInfo.getMcStatus()) || McStatusEnum.PAUSED.getMcStatusCode().equals(tmMcMoneyOffInfo.getMcStatus())) {

            /* 更新正式表数据状态 */
            TMMcMoneyOffInfo tmMcMoneyOffInfo = new TMMcMoneyOffInfo();
            tmMcMoneyOffInfo.setInstId(globalInstId);
            tmMcMoneyOffInfo.setMcNo(globalMcNo);
            tmMcMoneyOffInfo.setMcStatus(McStatusEnum.FORCE_ENDED.getMcStatusCode());
            tmMcMoneyOffInfo.setLastOprId(globalOprId);
            tmMcMoneyOffInfo.setUpdateTime(globalTimeStamp);
            tmMcMoneyOffInfo.setMcEndDate(DateUtil.getCurrentDate());
            tmMcMoneyOffInfo.setNfrcTmnlRsn(oprContent);
            returnCode = updatePausedMcMcStatusForEnabling(tmMcMoneyOffInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("强制结束进行中减免类营销活动信息更新正式表数据失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            //查询临时表状态
            checkTmPStatus(globalInstId, globalMcNo);
            /* 更新临时表数据状态 */
            TMPlatBizTmp tmPlatBizTmp = new TMPlatBizTmp();
            tmPlatBizTmp.setInstId(globalInstId);
            tmPlatBizTmp.setMcNo(globalMcNo);
            tmPlatBizTmp.setBizOpr(BizOprEnum.SUSPEND.getBizOprCode());
            tmPlatBizTmp.setBizStatus(bizStatus);
            tmPlatBizTmp.setMcStatus(McStatusEnum.FORCE_ENDED.getMcStatusCode());
            tmPlatBizTmp.setAuditStatus(auditStatus);
            tmPlatBizTmp.setLastOprId(globalOprId);
            tmPlatBizTmp.setLastUpdateTime(globalTimeStamp);

            returnCode = updatePausedMcForEnabling(tmPlatBizTmp);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("强制结束进行中减免类营销活动信息更新临时表数据失败！RETURN_CODE=<{}>", returnCode);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

        } else {
            rglog.error("营销活动状态异常，不可强制结束进行中的减免类营销活动！MC_STATUS=<{}>", tmMcMoneyOffInfo.getMcStatus());
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        dbsUtil.dbsEndTransaction(true);
    }

    /**
     * 发布成功更新临时表营销活动数据的状态、营销活动状态和审批状态
     *
     * @param tmPlatBizTmp 业务数据临时表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/25 22:33
     */
    private int updateSingleMcInfoForPublishing(TMPlatBizTmp tmPlatBizTmp) throws Exception {

        PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
        return platBizTmpMapper.updateSingleMcInfoForPublishing(tmPlatBizTmp);
    }

    /**
     * 发布成功更新整事表营销活动的营销活动状态和审批状态
     *
     * @param tmMcMoneyOffInfo 减免类营销活动信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/25 22:45
     */
    private int updateMcStatusForPublishing(TMMcMoneyOffInfo tmMcMoneyOffInfo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.updateMcStatusForPublishing(tmMcMoneyOffInfo, TABLE_NAME);
    }


    /**
     * 取待提交发布营销活动商户规则临时表中待提交发布的商户数据
     *
     * @param tmPlatBizTmp 业务数据临时表
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMPlatBizTmp> 业务数据临时表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/25 23:07
     */
    private List<TMPlatBizTmp> selectNewAddedMchntInfoForPublishing(TMPlatBizTmp tmPlatBizTmp) throws Exception {
        List<Object> tmMcMchntInfoList = new ArrayList<>();
        PageInfo pageInfo = new PageInfo();
        int i = 0;
        pageInfo.setPageIndex(i);
        pageInfo.setPageSize(9999);
        PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
        PageResult tmMcMchntInfoPageInfo = platBizTmpMapper.selectNewAddedMchntInfoForPublishing(tmPlatBizTmp, pageInfo);
        if (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult()) {
            tmMcMchntInfoList.addAll(tmMcMchntInfoPageInfo.getResult());
        }
        while (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult() && tmMcMchntInfoPageInfo.getResult().size() >= 1) {
            i++;
            pageInfo.setPageIndex(i);
            tmMcMchntInfoPageInfo = platBizTmpMapper.selectNewAddedMchntInfoForPublishing(tmPlatBizTmp, pageInfo);
            if (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult()) {
                tmMcMchntInfoList.addAll(tmMcMchntInfoPageInfo.getResult());
            }
        }
        List<TMPlatBizTmp> tmPlatBizTmpList = tmMcMchntInfoList.stream().map(item -> (TMPlatBizTmp) (item)).collect(Collectors.toList());
        return tmPlatBizTmpList;
    }

    /**
     * 将临时表新增商户数据插入正式表
     *
     * @param tmMcMchntInfoList 营销活动商户信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 00:16
     */
    private int insertMcMchntInfoListByBank(List<TMMcMchntInfo> tmMcMchntInfoList) throws Exception {

        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.insertMcMchntInfoListByBank(tmMcMchntInfoList);
    }

    /**
     * 更新商户数据正式表
     *
     * @param tmMcMchntInfoList 营销活动商户信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 00:16
     */
    private int updateMcMchntInfoListByBank(List<TMMcMchntInfo> tmMcMchntInfoList) throws Exception {

        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.updateMcMchntInfoListByBank(tmMcMchntInfoList);
    }

    /**
     * 活动中中添加商户流程发布成功更新减免类营销活动预算数据
     *
     * @param tmMcMoneyOffInfo 减免类营销活动信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 00:23
     */
    private int updateMcBudgetForPublishing(TMMcMoneyOffInfo tmMcMoneyOffInfo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.updateMcBudgetForPublishing(tmMcMoneyOffInfo);
    }

    /**
     * 发布拒绝更新正式表减免类营销活动审批状态和发布拒绝原因
     *
     * @param tmMcMoneyOffInfo 减免类营销活动信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:02
     */
    private int updateMcAuditStatusForPublishRefusal(TMMcMoneyOffInfo tmMcMoneyOffInfo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.updateMcAuditStatusForPublishRefusal(tmMcMoneyOffInfo, TABLE_NAME);
    }

    /**
     * 发布拒绝更新临时表减免类营销活动审批状态和发布拒绝原因
     *
     * @param tmPlatBizTmp 业务数据临时表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:12
     */
    private int updateMcAuditStatusForPublishingRefusal(TMPlatBizTmp tmPlatBizTmp) throws Exception {

        PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
        return platBizTmpMapper.updateMcAuditStatusForPublishingRefusal(tmPlatBizTmp);
    }

    /**
     * 启用已暂停营销活动更新正式表数据
     *
     * @param tmMcMoneyOffInfo 减免类营销活动信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:43
     */
    private int updatePausedMcMcStatusForEnabling(TMMcMoneyOffInfo tmMcMoneyOffInfo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.updatePausedMcMcStatusForEnabling(tmMcMoneyOffInfo, TABLE_NAME);
    }

    /**
     * 启用已暂停营销活动更新临时表数据
     *
     * @param tmPlatBizTmp 业务数据临时表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/26 01:37
     */
    private int updatePausedMcForEnabling(TMPlatBizTmp tmPlatBizTmp) throws Exception {

        PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
        return platBizTmpMapper.updatePausedMcForEnabling(tmPlatBizTmp);
    }

    /* 生成外围系统流水号
     * @param instId
     * @param sysSeqNo
     * @return
     */
    protected String genServiceSn(String instId, String sysSeqNo) {
        /*3位法人行号+4位系统标识+000+2位序号+9+6位流水号*/
        return instId + "0492" + "000" + sysSeqNo.substring(24, 26) + "9" + sysSeqNo.substring(26, 32);
    }

    /**
     * 查询当前最大记录顺序号
     *
     * @param publishMoneyOffMcRequest 减免类活动发布接口请求对象
     * @return int 当前最大记录顺序号
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/7/8 17:33
     */
    private int checkRecordIndex(PublishMoneyOffMcRequest publishMoneyOffMcRequest) throws Exception {

        /* 组装数据库操作实体类 */
        TMMcFundInfo tmMcFundInfo = new TMMcFundInfo();
        tmMcFundInfo.setInstId(globalInstId);
        tmMcFundInfo.setMcNo(globalMcNo);
        tmMcFundInfo.setPayerAcctId(globalOprId);
        tmMcFundInfo.setPayerAcctType(QueryTypeEnum.BANK_QUERY_TYPE.getQueryTypeCode());

        /* 查询数据 */
        TMMcFundInfoMapper tmMcFundInfoMapper = new TMMcFundInfoMapperImpl();
        int recordIndex = tmMcFundInfoMapper.checkMaxmiumRecordIndexInfo(tmMcFundInfo);
        if (CommonConstant.ZERO <= recordIndex) {
            /* 数据库有记录,直接返回当前数据 */
            return recordIndex;
        } else {
            /* 数据库无记录,返回-1 */
            return CommonConstant.MINUS_ONE;
        }
    }

    /**
     * 将数据插入数据库
     *
     * @param recordIndex              记录顺序号
     * @param publishMoneyOffMcRequest 减免类活动发布接口请求对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/7/8 17:09
     */
    private void insertSingleRecordForMchntFundInfo(int recordIndex, PublishMoneyOffMcRequest publishMoneyOffMcRequest) throws Exception {

        /* 取数据库收款账户信息数据 */
        String headOfficeId = globalInstId + CommonConstant.DEFAULT_HEAD_OFFICE_SUFFIX;
        TCRoleAcctInfoMapper tcRoleAcctInfoMapper = new TCRoleAcctInfoMapperImpl();
        TCRoleAcctInfo tcRoleAcctInfo = tcRoleAcctInfoMapper.selectInstitutionMcAccountByOrgIdAndAccountCategory(globalInstId, CommonConstant.MOMP_SUBJECT, headOfficeId);
        if (null == tcRoleAcctInfo) {
            rglog.error("获取法人机构<{}>的总行机构<{}>的营销收款账户信息失败!", globalInstId, headOfficeId);
            throw new BizException(RespCodeEnum.NO_MC_ACCOUNT_INFO_ERROR.getRespCode(), RespCodeEnum.NO_MC_ACCOUNT_INFO_ERROR.getRespDesc());
        }

        /* 组装数据库操作实体类 */
        TMMcFundInfo tmMcFundInfo = new TMMcFundInfo();
        tmMcFundInfo.setInstId(globalInstId);
        tmMcFundInfo.setMcNo(globalMcNo);
        tmMcFundInfo.setRecordIndex(Integer.toString(recordIndex));
        tmMcFundInfo.setPayerAcctId(globalOprId);
        tmMcFundInfo.setPayerAcctType(QueryTypeEnum.BANK_QUERY_TYPE.getQueryTypeCode());
        tmMcFundInfo.setPayerAcctNo(publishMoneyOffMcRequest.getAcctInfoObk().getPayAcctNo());
        tmMcFundInfo.setPayerAcctName(publishMoneyOffMcRequest.getAcctInfoObk().getPayAcctName());
        tmMcFundInfo.setPayeeAcctNo(tcRoleAcctInfo.getActualAcct());

        JsonTmpMoMcInfo jsonTmpMoMcInfo = JsonOperation.parseMoMcInfoTmpBizData1(this.tmPlatBizTmp, rglog);
        if (CommonConstant.SPONSOR_BANK.equals(jsonTmpMoMcInfo.getSponsor())) {
            tmMcFundInfo.setFundAmt(jsonTmpMoMcInfo.getBudget());
        } else {
            tmMcFundInfo.setFundAmt(jsonTmpMoMcInfo.getBankBudget());
        }

        tmMcFundInfo.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmMcFundInfo.setCreateTime(globalTimeStamp);

        /* 插入数据 */
        TMMcFundInfoMapper tmMcFundInfoMapper = new TMMcFundInfoMapperImpl();
        int returnCode = tmMcFundInfoMapper.insertSingleRecordForMchntFundInfo(tmMcFundInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("法人机构<{}>的营销活动<{}>的出资方<{}>的打款通知数据新增失败! RETURN_CODE=<{}>", globalInstId, globalMcNo, globalOprId, returnCode);
            throw new BizException(RespCodeEnum.RECORD_MC_FUND_INFO_ERROR.getRespCode(), RespCodeEnum.RECORD_MC_FUND_INFO_ERROR.getRespDesc());
        }
    }

    /**
     * 查询营销活动临时表活动信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @throws Exception
     */
    private void checkTmPStatus(String instId, String mcNo) throws Exception {
        PlatBizTmpMapper platBizTmpMapper = new PlatBizTmpMapperImpl();
        TMPlatBizTmp tmPlatBizTmp = platBizTmpMapper.selectTmpMcInfo(instId, mcNo, TABLE_NAME);
        if (null != tmPlatBizTmp) {
            auditStatus = tmPlatBizTmp.getAuditStatus();
            bizStatus = tmPlatBizTmp.getBizStatus();
        }
    }

    /**
     * 获取营销活动商户信息列表(正式表)
     *
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMMcMchntInfo> 营销活动商户信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/28 18:35
     */
    private List<Object> getAllMcMchntListInfoByinstIdMcMoFlag(String exitFlag, String newMchntFlag) throws Exception {
        List<Object> tmMcMchntInfoList = new ArrayList<>();
        PageInfo pageInfo = new PageInfo();
        int i = 0;
        pageInfo.setPageIndex(i);
        pageInfo.setPageSize(9999);
        TMMcMchntInfo tmMcMchntInfo = new TMMcMchntInfo();
        tmMcMchntInfo.setInstId(globalInstId);
        tmMcMchntInfo.setMcNo(globalMcNo);
        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        PageResult tmMcMchntInfoPageInfo = mcMchntInfoMapper.selectMcMchntInfoListByinstIdMcMoFlag(globalInstId, globalMcNo, exitFlag, newMchntFlag, pageInfo);
        if (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult()) {
            tmMcMchntInfoList.addAll(tmMcMchntInfoPageInfo.getResult());
        }
        while (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult() && tmMcMchntInfoPageInfo.getResult().size() >= 1) {
            i++;
            pageInfo.setPageIndex(i);
            tmMcMchntInfoPageInfo = mcMchntInfoMapper.selectMcMchntInfoListByinstIdMcMoFlag(globalInstId, globalMcNo, exitFlag, newMchntFlag, pageInfo);
            if (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult()) {
                tmMcMchntInfoList.addAll(tmMcMchntInfoPageInfo.getResult());
            }
        }
        return tmMcMchntInfoList;
    }
}
